package org.activequant.core.util;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

import org.activequant.core.domainmodel.data.TickerNews;
import org.activequant.core.domainmodel.data.TickerNewsSeries;
import org.activequant.core.types.TimeStamp;
import org.activequant.util.exceptions.ValueNotFoundException;

/**
* A TickerNewsSeries, TimeSeries and ArrayList subclass. Holds the following associated variable:
* <ul>
* <li>cache(TreeMap&lt;TimeStamp,TickerNews&gt;)</li>
* </ul>
* <br>
* <b>History:</b><br>
*  - [03.05.2007] Created (Erik Nijkamp)<br>
*  
*  @author Erik Nijkamp
*/
public class TickerNewsSeriesHash extends TickerNewsSeries {

	private static final long serialVersionUID = 5254689954795874715L;
	/**
	 * private TreeMap&lt;TimeStamp,TickerNews&gt; cache = new TreeMap&lt;TimeStamp,TickerNews&gt;();
	 */
	private TreeMap<TimeStamp, TickerNews> cache = new TreeMap<TimeStamp, TickerNews>();
	/**
	 * 
	 * @param timeSeries
	 */
	public TickerNewsSeriesHash(TickerNewsSeries timeSeries) {
		super(timeSeries);
		rebuildCache();
	}
	/**
	 * clears and then re-fills the associated cache(TreeMap&lt;TimeStamp,TickerNews&gt;) using the TickerNews elements of this TickerNewsSeriesHash(TickerNewsSeries and ArrayList subclass) as values and their
	 * timeStamp(TimeStamp)'s as the keys.
	 */
	private void rebuildCache() {
		cache.clear();
		for(TickerNews tickerNews: this) {
			cache.put(tickerNews.getTimeStamp(), tickerNews);
		}
	}
	/**
	 * returns the timeStamp(TimeStamp) of the TickerNews element at the given i(int) position in this TickerNewsSeriesHash(TickerNewsSeries and ArrayList subclass)
	 * @param i
	 * @return
	 */
	public TimeStamp getTimeStamp(int i) {
		return get(i).getTimeStamp();
	}
	/**
	 * returns a TickerNewsSeries(ArrayList) holding the TickerNews objects (from the TickerNews values in the associated cache(TreeMap&lt;TimeStamp,TickerNews&gt;)) 
	 * whose timeStamp(TimeStamp)'s is in the given start-end(TimeStamp) interval
	 */
	public TickerNewsSeries getTimeFrame(TimeStamp start, TimeStamp end) {        
	    SortedMap<TimeStamp, TickerNews> subMap = cache.subMap(start, end);
	    TickerNewsSeries timeSeries = new TickerNewsSeries();
	    timeSeries.addAll(subMap.values());        
	    return timeSeries;
	}
	/**
	 * returns whether the associated cache(TreeMap&lt;TimeStamp,TickerNews&gt;) contains the given date(TimeStamp) as key
	 */
	public boolean containsTimeStamp(TimeStamp date) {
		return cache.containsKey(date);
	}
	/**
	 * returns the TickerNews mapped under the given date(TimeStamp) in the associated cache(TreeMap&lt;TimeStamp,TickerNews&gt;)
	 * @param date
	 * @return
	 */
	public TickerNews getTickerNewsByTimeStamp(TimeStamp date) {
		return cache.get(date);
	}
	/**
	 * returns the position of the given date(TimeStamp) among the TimeStamp keys in the associated cache(TreeMap&lt;TimeStamp,TickerNews&gt;)
	 */
	public int getTimeStampPosition(TimeStamp date) throws ValueNotFoundException {
		List<TimeStamp> dates = new LinkedList<TimeStamp>();
		dates.addAll(cache.keySet());
		int pos = Collections.binarySearch(dates, date);
		if (pos < 0)
			throw new ValueNotFoundException("Cannot find value for date '" + date + "'.");
		return pos;
	}
}